const fs = require('fs')
const { resolve } = require('path')
const { parseScript, checkType, getPosition } = require('./utils')

function provideDefinitionFn(document, position, token) {
  const fileName = document.fileName
  const word = document.getText(document.getWordRangeAtPosition(position))
  const lineNo = position.line
  const text = document.getText()
  const line = getLineText(text, lineNo)
  const type = checkType(word, line)
  let keys = []
  return new Promise(resolve => {
    if (type === 'file') {
      let allPath = getAllPath(line, fileName)
      getPath(allPath).then(path => {
        resolve({
          isFile: true,
          path: path,
          pos: { x: 0, y: 0 }
        })
        // return new vscode.Location(vscode.Uri.file(path), new vscode.Position(0, 0));
      })
    } else {
      if (keys.length === 0) {
        keys = ['methods', 'computed', 'props', 'data']
      }
      let reg = /(<script>)([\s\S]*)<\/script>/
      let m = text.match(reg)
      let map = parseScript(m[2])
      let pos = getPosition(map, keys, word, m)
      resolve({
        isFile: false,
        path: fileName,
        pos
      })
      // return new vscode.Location(vscode.Uri.file(fileName), new vscode.Position(pos.y, pos.x));
    }
  })

}

function getLineText(text, lineNo) {
  let lines = text.split('\n')
  return lines[lineNo] || ''
}

function getAllPath(line, filename) {
  const defaultAlias = {
    '@': 'src/'
  }
  filename = filename.split(/\\|\//).join('/')
  let idx1 = line.indexOf('\'') + 1
  let idx2 = line.indexOf('\'', idx1)
  let tmp = line.substring(idx1, idx2)
  for (let key in defaultAlias) {
    if (!tmp.includes(key)) continue
    let val = defaultAlias[key]
    val = val.split(/\\|\//).join('/')
    let idx0 = filename.indexOf(val)
    let start = filename.substring(0, idx0 + val.length)
    tmp = tmp.replace('@/', '')
    tmp = resolve(start, tmp)
  }
  let start = filename.substring(0, filename.lastIndexOf('/'))
  tmp = resolve(start, tmp)
  // 完整路径无需额外处理
  if (tmp.includes('.')) {
    return [tmp]
  }
  const lastWork = tmp.substr(tmp.lastIndexOf('/'))
  let concatpath = ['.js', '.vue', '/index.js', '/index.vue', `${lastWork}.js`, `${lastWork}.vue`]
  let allPath = []
  concatpath.forEach(o => allPath.push(tmp + o));
  return allPath
}

function getPath(allPath) {
  let ps = []
  function access(path) {
    return new Promise(resolve => {
      fs.access(path, fs.constants.F_OK, (err) => {
        resolve(err ? '' : path)
      });
    })
  }

  allPath.forEach(o => {
    ps.push(access(o))
  })

  return Promise.all(ps).then(res => {
    return res.filter(_ => _.trim())[0]
  })
}
module.exports = { provideDefinitionFn }
